#include <iostream>
#include <stdlib.h>
#include "node.h"
#include "swarmBinHeader.h"

class swarmBin {
	public:

	std::vector<node *> * nodes;
	int x;
	int y;
	bool colors;

	swarmBin( int x, int y, int hypos, int seed ) {
//		srand();

		this->nodes = new std::vector<node *>;
		int count = x * y;
		node * n;

		colors = false;

		for ( int i = 0; i < count; ++i ) {
			n = new node ( hypos );
			n->randomize();
			this->nodes->push_back( n );
		}
		this->x = x;
		this->y = y;
		this->connectNodes();
	}

	void seed( unsigned int i ) {
		srand(i);
	}

	int getX() { return this->x; }
	int getY() { return this->y; }

	node * getNode( int x, int y ) {
		int index = (( this->getY() * y ) + x);
		if ( index <= this->nodes->size() ) {
			return nodes->at( index );
		} else {
			std::cout << "Accessing out of Bounds Node! This is an issue! SwarmBin, getNode\n";
			return NULL;
		}
	}

	virtual void setColor( bool s ) {
		this->colors = s;
	}

	virtual bool binIsComplete() {
		int c = ( this->getX() * this->getY() );
		bool ret = true;

		for ( int ix = 0; ix < this->getX(); ++ix ) {
			for ( int iy = 0; iy < this->getY(); ++iy ) {
				if ( ! this->getNode( ix, iy )->strictCheck() ) {
					ret = false;
				}
			}
		}
		return ret;
	}

	virtual void diagDump() {
		for ( int ix = 0; ix < this->getX(); ++ix ) {
			for ( int iy = 0; iy < this->getY(); ++iy ) {
				if ( this->colors ) {
					int s = this->getNode(ix,iy)->getStatus();

					if ( s == 0 ) {
						std::cout << COLOR_RED;
					} else if ( s == 1 ) {
						std::cout << COLOR_BLUE;
					} else if ( s == 2 ) {
						std::cout << COLOR_YELLOW;
					} else if ( s == 3 ) {
						std::cout << COLOR_GREEN;
					} else {
						std::cout << COLOR_WASH;
					}
				}
				std::cout
					<< this->getNode(ix,iy)->getStatus()
					<< " ";
			}
			std::cout << "\n";
		}

		if ( this->colors ) {
			std::cout << COLOR_WASH << "\n";
		} else {
			std::cout << "\n";
		}
	}

	virtual void deNodeLockGrid() {
		for ( int ix = 0; ix < this->getX(); ++ix ) {
			for ( int iy = 0; iy < this->getY(); ++iy ) {
				node * n = this->getNode( ix, iy );
				if ( ! n->strictCheck() && n->isLocked() ) {
//					std::cout << "Locked Node is in Conflict\n";
				} else if ( ! n->strictCheck() && !n->inFrozenConflict() ) {
					n->randomize();
				}
			}
		}
	}

	virtual void resetNodes() {
		for ( int ix = 0; ix < this->getX(); ++ix ) {
			for ( int iy = 0; iy < this->getY(); ++iy ) {
				node * n = this->getNode( ix, iy );
				n->resetRate();
			}
		}
		for ( int ix = 0; ix < this->getX(); ++ix ) {
			for ( int iy = 0; iy < this->getY(); ++iy ) {
				node * n = this->getNode( ix, iy );
				n->rateNodes();
			}
		}
	}

	virtual void connectNodes() {

		int ex = this->getX();
		int ey = this->getY();

		for ( int ix = 0; ix < ex; ++ix ) {
			for ( int iy = 0; iy < ey; ++iy ) {

				if ( ix > 0 ) {
					this->getNode( ix, iy )->linkNode( this->getNode( ix - 1, iy ) );
				}
				if ( ix < x - 1 ) {
					this->getNode( ix, iy )->linkNode( this->getNode( ix + 1, iy ) );
				}
				if ( iy > 0 ) {
					this->getNode( ix, iy )->linkNode( this->getNode( ix, iy - 1 ) );
				}
				if ( iy < y - 1 ) {
					this->getNode( ix, iy )->linkNode( this->getNode( ix, iy + 1 ) );
				}

//				std::cout << "Linking Node " << ix << "(X), " << iy << "(Y)\n";
			}
//			std::cout << "Linked Row\n";
//			std::cout << "X: " << this->getX() << ", Y: " << this->getY() << "\n";
		}
//		std::cout << "Fin\n";
	}
};
